#include "Parser.h"
#include <algorithm>


Parser::Parser(const string& filePath) : 
	filePath(filePath),
	nofLines(0),
	nofTokensInCurrentLine(0),
	nofTotalToken(0)
	{};

Parser::~Parser()
{
	/*delete input lines*/
	for (list<InputLine *>::iterator iter = lines.begin(); iter!= lines.end(); iter++) {
		delete *iter;
	}
};

const string* Parser::getFilePath() const{
	return &filePath;
}

void Parser::printErrors() const{
	cout << endl << "Errors:" << endl << "----------------------------------------" << endl;
	for (list<const string *>::const_iterator iter=errors.begin(); iter!=errors.end(); iter++) {
		cout << **iter;
	}
}

void Parser::printVarsAndFuncs() const{
	cout << endl << "Variables and Functions:" << endl << "----------------------------------------" << endl;
	for (list<const string *>::const_iterator iter=varsAndFuncs.begin(); iter!=varsAndFuncs.end(); iter++) {
		cout << **iter;
	}
}

void Parser::printStat() const{
	cout << endl << "Stat:" << endl << "----------------------------------------" << endl;
	cout<<"Total number of lines: " << getNofLines() << endl;
	cout << "Total number of tokens: " << getNofTotalToken() << endl;
	int lineNum = 1;
	for (list<InputLine *>::const_iterator iter=lines.begin(); iter!=lines.end(); iter++) {
		cout << "Line " << lineNum << " : " << (*iter)->getList().size() << endl;
		lineNum++;
	}
}

int Parser::getNofTotalToken() const{
	return nofTotalToken;
}

int Parser::getNofLines() const {
	return nofLines;
}

bool Parser::compile() {
	/*clear last compile results*/
	errors.clear();
	varsAndFuncs.clear();
	for (list<InputLine *>::iterator iter = lines.begin(); iter!= lines.end(); iter++) {
		delete *iter;
	}
	lines.clear();

	/*open file*/
	file.open(filePath);

	/*for each line create input line and analyze*/
	char line_char[Parser::LINE_MAX_SIZE];
	while (file.good() && !file.eof()) {
	
		file.getline(line_char, Parser::LINE_MAX_SIZE);
		nofLines++;
		string *line_str = new string(line_char);
		if (line_str == NULL) {
			return false;
		}


		InputLine *line = new InputLine(*line_str); 
		if (line == NULL) {
			delete line_str;
			return false;
		}
		nofTokensInCurrentLine = line->getList().size();
		nofTotalToken += nofTokensInCurrentLine;

		lines.push_back(line);

		analyzer.compileLine(line->getList());
	}
	analyzer.finishCompile();

	/*get compile information*/
	const list<const string *> analyzeErrors = analyzer.getErrors();
	this->errors.insert(errors.end(), analyzeErrors.begin(), analyzeErrors.end());
	
	const list<const string *> analyzeVarsAndFuncs = analyzer.getVarsAndFuncs();
	this->varsAndFuncs.insert(varsAndFuncs.end(), analyzeVarsAndFuncs.begin(), analyzeVarsAndFuncs.end());
	return true;
}